<?php

namespace Theatre\Model;


class PostGreSQL extends \Theatre\Model {
	/**
	 * @var @_connection The connection
	 */
	protected $_connection;


	/**
	 * @var $_config Config
	 */
	protected $_config;


	/**
	 * Contructor
	 */
	public function __construct($config) {
		$this->_config = $config;

		if (!extension_loaded('pgsql')) {
			throw new \Exception('PostGreSQL extension not available.');
		}

		parent::__construct();
	}


	/**
	 * Destructor
	 */
	public function __destruct() {
		parent::__construct();

		$this->close();
	}


	/**
	 * Connect to the database
	 */
	private function connect() {
		if (empty($this->_config['port'])) {
			$this->_config['port'] = '';
		}

		$conn  = "host='{$this->_config['host']}' port='{$this->_config['port']}' dbname='{$this->_config['database']}' ";
                $conn .= "user='{$this->_config['login']}' password='{$this->_config['password']}'";

		$this->_connection = $this->_config['persistent']
			? pg_pconnect($conn)
			: pg_connect($conn, PGSQL_CONNECT_FORCE_NEW);

		if (empty($this->_connection)) {
			// throw exceptions
			throw new \Exception('Cannot connect to the database');
		}
	}


	/**
	 * Run query
	 */
	public function dbQuery($query) {
		$this->_ensureConnected();

		$args = func_get_args();
		array_shift($args);

		if (empty($args)) {
			return pg_query($this->_connection, $query);
		}

		return pg_query_params($this->_connection, $query, $args);
	}


	/**
	 * Run query
	 */
	public function dbQueryFirst($query) {
		$args = func_get_args();
		// args[0] is the name of the function, replace it with $query
		$args[0] = $query;
		
		// preserve the parameters
		$result = call_user_func_array(array($this, 'dbQuery'), $args);

		return $this->dbFetchObject($result);
	}

	/**
	 * Run Procedure/function
	 */
	public function dbRun($fnName) {
		$this->_ensureConnected();

		$args = func_get_args();
		// args[0] is the name of the function, replace it with $query
		$args[0] = "select * from {$fnName}";

		return call_user_func_array(array($this, 'dbQueryFirst'), $args);
	}


	/**
	 * Run Procedure/function
	 */
	public function dbRunResult($fnName) {
		$this->_ensureConnected();

		$args = func_get_args();
		// args[0] is the name of the function, replace it with $query
		$args[0] = "select * from {$fnName}";

		return call_user_func_array(array($this, 'dbQuery'), $args);
	}


	/**
	 * Fetch object
	 */
	public function dbFetchObject($result) {
		if (is_array($result)) {
			return $result;
		}

		if (empty($result)) {
			return null;
		}

		return pg_fetch_object($result);
	}


	/**
	 * Get the last inserted id
	 */
	public function lastInsertedId() {
		return null;
	}


	/**
	 * Get last error
	 */
	public function getLastError() {
		$this->_ensureConnected();

		return pg_last_error($this->_connection);
	}


	/**
	 * Close connection
	 */
	public function close() {
		if ($this->_connection) {
			pg_close($this->_connection);
		}
	}


	/**
	 * Start transaction
	 */
	public function startTransaction() {
		$this->_ensureConnected();

		pg_query('BEGIN;');
	}


	/**
	 * Commit
	 */
	public function commit() {
		$this->_ensureConnected();

		pg_query('COMMIT');
	}


	/**
	 * Rollback
	 */
	public function rollback() {
		$this->_ensureConnected();

		pg_query($this->_connection, 'ROLLBACK');
	}


	/**
	 * Make sure that we are connected
	 */
	private function _ensureConnected() {
		if (!$this->_connection) {
			$this->connect();
		}
	}
}
